﻿#include "OiPCH.hpp"
#include "Ctrl/OiDocket.hpp"
#include "RibbonControls/RcOfficePopupWindow.hpp"
#include "RibbonControls/RcRibbonPage.hpp"
#include "RibbonControls/RcRibbonGroup.hpp"
#include <windows.h>

namespace Oi { namespace Appl {

class FlangeXWindowImpl : public Impl<FlangeXWindow>
{
public:
    FlangeXWindowImpl()
    {
        qRegisterMetaTypeStreamOperators<Flow::Operator*>("Flow::Operator*");
        qRegisterMetaTypeStreamOperators<Flow::OperatorPtr>("Flow::OperatorPtr");
    }

    ~FlangeXWindowImpl()
    {
    }

public:
    void init();
    void exit();

public:
    ProgViewer* _progViewer;
    ProgDetail* _progDetail;
    QDockWidget* _progDetailDocket;

    ProgOutput* _progOutput;

    QDockWidget* _progOutputDocket;

    QAction* actionSwitch;
    QAction* actionStart;
    QAction* actionSetting;
    Oi::RibbonGroup* groupProduct;
    Oi::RibbonGroup* groupStatus;
    Oi::RibbonGroup* groupSetting;

    QString _product;

    QString _stationFile;

    bool _chooseMode;
};

void FlangeXWindowImpl::init()
{
    OI_Q(FlangeXWindow);

    _chooseMode = false;

    OI_ASSERT(!qApp->property("mainWindow").isValid());

    QSettings* settings = Core::OiSettings()->object();

    qApp->setStyle("ribbonstyle");

    Core::Registry::instance()->log("MainWindow", q);

    auto actionBar = new Oi::RibbonQuickActionBar();
    QMenu* fileMenu = actionBar->addMenu(FlangeXWindow::tr("文件"));
    QMenu* execMenu = actionBar->addMenu(FlangeXWindow::tr("调试"));
    QMenu* toolMenu = actionBar->addMenu(FlangeXWindow::tr("工具"));
    QMenu* viewMenu = actionBar->addMenu(FlangeXWindow::tr("视图"));
    QMenu* helpMenu = actionBar->addMenu(FlangeXWindow::tr("帮助"));

    q->ribbonBar()->attachQuickActionBar(actionBar);

    if (Oi::RibbonPage* pageButtons = q->ribbonBar()->addPage(FlangeXWindow::tr("首页")))
    {
        //pageButtons->setVisible(true);
        //pageButtons->setPageVisible(true);

        groupProduct = pageButtons->addGroup(FlangeXWindow::tr("产品定义"));
        if (groupProduct)
        {
            groupProduct->setTitleVisible(false);
            groupProduct->setOptionButtonVisible(false);

            actionSwitch = groupProduct->addAction(QIcon(":/resources/images/Switch.png"), FlangeXWindow::tr("切换产品"), Qt::ToolButtonTextUnderIcon);
            actionSwitch->setCheckable(false);
            q->connect(actionSwitch, SIGNAL(triggered()), q, SLOT(onSwitchTriggered()));
        }

        groupStatus = pageButtons->addGroup(FlangeXWindow::tr("运行状态"));
        if (groupStatus)
        {
            groupStatus->setEnabled(false);
            groupStatus->setTitleVisible(false);
            groupStatus->setOptionButtonVisible(false);

            actionStart = groupStatus->addAction(QIcon(":/resources/images/Run.png"), FlangeXWindow::tr("开始检测"), Qt::ToolButtonTextUnderIcon);
            q->connect(actionStart, SIGNAL(triggered()), q, SLOT(onRunTriggered()));
        }

        groupSetting = pageButtons->addGroup(FlangeXWindow::tr("标定相机"));
        if (groupSetting)
        {
            groupSetting->setEnabled(true);
            groupSetting->setTitleVisible(false);
            groupSetting->setOptionButtonVisible(false);

            actionSetting = groupSetting->addAction(QIcon(":/resources/images/CameraSetting.png"), FlangeXWindow::tr("标定"), Qt::ToolButtonTextUnderIcon);
            q->connect(actionSetting, SIGNAL(triggered()), q, SLOT(onSettingTriggered()));
        }
    }

    q->ribbonBar()->setFrameThemeEnabled(true);

    q->ribbonBar()->showQuickActionBar(false);

    q->statusBar();

    QLibrary("OiOperators.dll").load();

    QStringList packages;

    foreach (const QFileInfo& entry, QDir("packages").entryInfoList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot))
    {
        if (QFile::exists(entry.absoluteFilePath() + "\\" + entry.fileName() + ".dll"))
        {
            packages << entry.absoluteFilePath();
        }
    }

    if (!packages.empty())
    {
        qputenv("PATH", (QProcessEnvironment::systemEnvironment().value("PATH") + ";" + packages.join(";")).toLocal8Bit());
    }

    void* routine = NULL;

    foreach (const QFileInfo& entry, QDir("packages").entryInfoList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot))
    {
        if (QFile::exists(entry.absoluteFilePath() + "\\" + entry.fileName() + ".dll"))
        {
            if ((routine = QLibrary::resolve(entry.absoluteFilePath() + "\\" + entry.fileName() + ".dll", "OiPackageInit")) != NULL)
            {
                reinterpret_cast<void (*)(void)>(routine)();
            }
        }
    }

    qApp->setProperty("mainWindow", QVariant::fromValue<QWidget*>(q));

    _progViewer = new ProgViewer(q);
    q->setCentralWidget(_progViewer);
    qApp->setProperty("operViewer", QVariant::fromValue<QWidget*>(_progViewer->operViewer()));

    _progDetailDocket = new Ctrl::Docket(FlangeXWindow::tr("引擎检测"));
    _progDetailDocket->setObjectName("progDetail");
    _progDetail = new ProgDetail(_progDetailDocket);
    _progDetail->setWindowTitle(_progDetailDocket->windowTitle());
    _progDetailDocket->setWidget(_progDetail);
    q->addDockWidget(Qt::LeftDockWidgetArea, _progDetailDocket);

    _progOutputDocket = new Ctrl::Docket(FlangeXWindow::tr("程序输出"), q);
    _progOutputDocket->setObjectName("progOutput");
    _progOutput = new ProgOutput(_progOutputDocket);
    _progOutput->setWindowTitle(_progOutputDocket->windowTitle());
    _progOutputDocket->setWidget(_progOutput);
    q->addDockWidget(Qt::RightDockWidgetArea, _progOutputDocket);

    fileMenu->addAction(FlangeXWindow::tr("切换"), q, SLOT(onSwitchTriggered()));
    fileMenu->addSeparator();
    fileMenu->addAction(FlangeXWindow::tr("关闭"), q, SLOT(onClose()));

    execMenu->addAction(FlangeXWindow::tr("启用调试信息"), q, SLOT(onDebugger()))->setCheckable(true);

    toolMenu->addAction(FlangeXWindow::tr("设置启动密码..."), q, SLOT(onPassword()));

    viewMenu->addAction(_progOutputDocket->toggleViewAction());
    viewMenu->addAction(_progDetailDocket->toggleViewAction());

    helpMenu->addAction(FlangeXWindow::tr("帮助"), q, SLOT(onHelp()));
    helpMenu->addAction(FlangeXWindow::tr("注册"));
    helpMenu->addAction(FlangeXWindow::tr("关于"), q, SLOT(onAbout()));

    QMetaObject::invokeMethod(q, "onReady", Qt::QueuedConnection);
}

void FlangeXWindowImpl::exit()
{
}

FlangeXWindow::FlangeXWindow(QWidget *parent) : Oi::RibbonMainWindow(parent, 0)
{
    OI_I(FlangeXWindow)->init();
}

FlangeXWindow::~FlangeXWindow()
{
    OI_E(FlangeXWindow)->exit();
}

void FlangeXWindow::onDebugger()
{
}

void FlangeXWindow::onPassword()
{
    bool ok = false;

    QString text;

    if (!(text = QInputDialog::getText(this, FlangeXWindow::tr("设置启动密码"), FlangeXWindow::tr("新密码"), QLineEdit::Password, "", &ok, Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint)).isEmpty())
    {
        Core::OiSettings()->object()->setValue("WindowPassword", QCryptographicHash::hash((Core::OiBaseCreatorName() + text).toLatin1(), QCryptographicHash::Md5));
    }
    else if (ok)
    {
        Core::OiSettings()->object()->setValue("WindowPassword", "");
    }
}

void FlangeXWindow::onHelp()
{
}

void FlangeXWindow::onReady()
{
    OI_F(FlangeXWindow);
}

void FlangeXWindow::onAbout()
{
}

void FlangeXWindow::onClose()
{
    OI_F(FlangeXWindow);

    d->_progDetail->quit();
}

void FlangeXWindow::keyPressEvent(QKeyEvent* evt)
{
    Oi::RibbonMainWindow::keyPressEvent(evt);
}

void FlangeXWindow::keyReleaseEvent(QKeyEvent* evt)
{
    Oi::RibbonMainWindow::keyReleaseEvent(evt);
}

void FlangeXWindow::closeEvent(QCloseEvent* evt)
{
    onClose();
}

void FlangeXWindow::appendHistory(const QString& text)
{
    OI_IMPL()->_progOutput->append("<span style=\"color:red\">" + text + "</span>");
}

void FlangeXWindow::appendWarning(const QString& text)
{
    OI_IMPL()->_progOutput->append("<span style=\"color:orange\">" + text + "</span>");
}

void FlangeXWindow::appendMessage(const QString& text)
{
    OI_IMPL()->_progOutput->append(text);
}

void FlangeXWindow::onSwitchTriggered()
{
    OI_F(FlangeXWindow);

    FlangeXProductDialog productDialog(Core::OiGetPermanentDir(ProjectDir), this);

    connect(&productDialog, SIGNAL(appendProject()), this, SLOT(onAppendProduct()));
    connect(&productDialog, SIGNAL(modifyProject(const QString&)), this, SLOT(onModifyProduct(const QString&)));
    connect(&productDialog, SIGNAL(deleteProject(const QString&)), this, SLOT(onDeleteProduct(const QString&)));

    if (!d->_product.isEmpty())
    {
        productDialog.setCurrent(d->_product);
    }

    if (productDialog.exec() == QDialog::Accepted)
    {
        onSelectProduct(productDialog.current());
    }

    if (!d->_chooseMode)
    {
        d->_chooseMode = true;
    }
}

void FlangeXWindow::onRunTriggered()
{
    OI_F(FlangeXWindow);

    if (!d->_chooseMode)
    {
        QMessageBox::information(this,tr("提示"),tr("请先选择产品!"), QMessageBox::Ok);
        return;
    }

    QAction* action = qobject_cast<QAction*>(sender());

    if (d->actionStart->text() == FlangeXWindow::tr("开始检测"))
    {
        onLoopClicked();
    }
    else
    {
        onStopClicked();
    }
}

void FlangeXWindow::onSettingTriggered()
{
    FlangeXCalibration calib(this, this);

    if (calib.exec() == QDialog::Accepted)
    {

    }
}

void FlangeXWindow::onAppendProduct()
{
    FlangeXProductDialog* productDialog = qobject_cast<FlangeXProductDialog*>(sender());

    bool ok = false;

    QString text;

    if (!(text = QInputDialog::getText(this, FlangeXWindow::tr("添加产品"), FlangeXWindow::tr("输入产品名称"), QLineEdit::Normal, "", &ok, Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint)).isEmpty())
    {
        QString root = Core::OiGetPermanentDir(ProjectDir);
        QString directory = root + "\\" + text;
        QString selectedProduct = productDialog->current();

        if (QFile::exists(directory))
        {
            QMessageBox::information(this, tr("提示"), tr("产品名称已存在！"), QMessageBox::Ok);
            return;
        }

        if (!QDir().mkdir(directory))
        {
            QMessageBox::information(this, tr("提示"), tr("无法创建产品文件夹！"), QMessageBox::Ok);
            return;
        }

//         for (int i = 0; i < SITENUMS; i++)
//         {
//             QFile::copy(selectedProduct + QString("\\Program%1.oif").arg(i), directory + QString("\\Program%1.oif").arg(i));
//         }

        productDialog->refresh();
    }
}

void FlangeXWindow::onSelectProduct(const QString& product)
{
    OI_F(FlangeXWindow);

    d->_product = product;

    Core::Settings::instance()->setValue("Product", product);

    d->groupStatus->setEnabled(false);

    d->_stationFile  = product;

    bool success = true;

    if (QFile::exists(d->_stationFile))
    {
        if (d->_progDetail->load(d->_stationFile) == 0)
        {
            d->_progDetail->program()->setProperty("path", d->_stationFile);
        }
        else
        {
            success = false;
            Core::OiAppendHistory("错误：加载产品工位 [" + d->_stationFile + "] 失败！");
        }
    }
    else
    {
        success = false;
        Core::OiAppendHistory("错误：产品工位 [" + d->_stationFile + "] 不存在！");
    }

    if (success)
    {
        d->groupStatus->setEnabled(true);
    }
}

void FlangeXWindow::onModifyProduct(const QString& product)
{
    FlangeXProductDialog* productDialog = qobject_cast<FlangeXProductDialog*>(sender());

    bool ok = false;

    QString name = QFileInfo(productDialog->current()).fileName();;

    QString text;

    if (!(text = QInputDialog::getText(this, FlangeXWindow::tr("修改名称"), FlangeXWindow::tr("输入产品名称"), QLineEdit::Normal, name, &ok, Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint)).isEmpty())
    {
        if (text == name)
        {
            return;
        }

        QString root = Core::OiGetPermanentDir(ProjectDir);
        QString directory = root + "\\" + text;
        QString selectedProduct = productDialog->current();

        if (QFile::exists(directory))
        {
            QMessageBox::information(this, tr("提示"), tr("产品名称已存在！"), QMessageBox::Ok);
            return;
        }

        QDir().rename(selectedProduct, directory);

        productDialog->refresh();
    }
}

void FlangeXWindow::onDeleteProduct(const QString& product)
{
    if (QMessageBox::information(this, tr("确定"), tr("确认删除此产品，删除后将无法还原！"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
    {
        foreach (const QFileInfo& item, QDir(product).entryInfoList(QDir::Files))
        {
            QFile::remove(item.filePath());
        }

        if (QDir().rmdir(product))
        {
            qobject_cast<FlangeXProductDialog*>(sender())->refresh();
        }
    }
}

QWidget* FlangeXWindow::getOperViewer(QString name) const
{
    return OI_IMPL()->_progViewer->operViewer();
}

QWidget* FlangeXWindow::getHistViewer(QString name) const
{
    return OI_IMPL()->_progViewer->histViewer();
}

void FlangeXWindow::onLoopClicked()
{
    OI_F(FlangeXWindow);
    d->_progDetail->executeOnce();
    d->actionStart->setIcon(QIcon(":/resources/images/StopRun.png"));
    d->actionStart->setText(FlangeXWindow::tr("停止检测"));
    d->actionSwitch->setEnabled(false);
}

void FlangeXWindow::onStopClicked()
{
    OI_F(FlangeXWindow);
    d->_progDetail->executeStop();
    d->actionStart->setIcon(QIcon(":/resources/images/Run.png"));
    d->actionStart->setText(FlangeXWindow::tr("开始检测"));
    d->actionSwitch->setEnabled(true);
}

} }
